// 顶点着色器
BABYLON.Effect.ShadersStore["waterRenderVertexShader"] = /* glsl */ `
precision highp float;

// 内置属性
attribute vec3 position;
attribute vec2 uv;

// 内置变量
uniform mat4 worldViewProjection;
uniform mat4 world;
uniform mat4 view;
uniform mat4 projection;
uniform float time;
uniform vec2 iResolution;
uniform sampler2D noiseTexture;
#define PI 3.14159265359
// 传递给片元着色器
varying vec2 vUV;
// varying vec3 worldNormal;
varying vec3 worldPosition3;

float getWave(vec2 worldPosVEC2){
    float decay_A = 0.77;  // 上升系数
    float decay_w = 1.79;  // 衰减系数
    float L = 10.0;    // 波峰到波峰之间的距离
    float A = 1.0;    // 波峰的高度
    float S = 10.0;       // 速度,每秒波峰移动的距离
    float w = 2.0*PI/L;     // 角频率常数
    float f = S * 2.0* PI /L; // 相常数
    float H = 0.0;
    vec3 dxdydz = vec3(0.0,1.0, 0.0);   // 偏导数
    float dhdx = 0.0;
    float dhdz = 0.0;
    float dhdx_total = 0.0;
    float dhdz_total = 0.0;
    int maxTimes = 2;
    // int mystep = int(rd * float(maxTimes)) ;
    vec2 dir = vec2(0.4,0.1);     // 随机生成波峰移动的方向
    for(int i=0;i<maxTimes;i++){
      vec2 uv = worldPosVEC2;
      vec2 iuv = floor(uv);
      vec2 fuv = fract(uv);
      A *= decay_A;
      w *= decay_w;  
      f *= decay_A;
      float D = dir.x * uv.x + dir.y*uv.y;    // 波峰移动的方向
      float u1 = sin(D*w+time*f);
      H += A * exp(u1-1.0);
    //   dir.x *= -1.1;
      // float n1 = pNoise(worldPosVEC2,2);
      // float noise = texture2D(noiseTexture, uv).x;
      // dir = vec2(noise);

    }
    dxdydz = normalize(vec3(-dhdx_total,1.0,-dhdz_total));
    // return vec4(H,dxdydz);
    return H;
}
void main(void) {
    vUV = uv;
    vec3 newPosition = position;
    vec4 worldPosition = world * vec4(newPosition, 1.0);
    float height = getWave(worldPosition.xz+1e3);
    worldPosition.y += height;
    worldPosition3 = worldPosition.xyz;
    vec4 viewPosition = view * worldPosition;
    vec4 projectionPosition = projection * viewPosition;
    gl_Position = projectionPosition;
}
`;
// 片元着色器
BABYLON.Effect.ShadersStore["waterRenderFragmentShader"] = /* glsl */ `
precision highp float;

varying vec2 vUV;
uniform float time;
uniform vec2 iResolution;
uniform mat4 view;
uniform sampler2D noiseTexture;
// varying vec3 worldNormal;
varying vec3 worldPosition3;
#define PI 3.14159265359

float rand(vec2 c){
	return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

float noise(vec2 p, float freq ){
	float unit = iResolution.x/freq;
	vec2 ij = floor(p/unit);
	vec2 xy = mod(p,unit)/unit;
	//xy = 3.*xy*xy-2.*xy*xy*xy;
	xy = .5*(1.-cos(PI*xy));
	float a = rand((ij+vec2(0.,0.)));
	float b = rand((ij+vec2(1.,0.)));
	float c = rand((ij+vec2(0.,1.)));
	float d = rand((ij+vec2(1.,1.)));
	float x1 = mix(a, b, xy.x);
	float x2 = mix(c, d, xy.x);
	return mix(x1, x2, xy.y);
}

float pNoise(vec2 p, int res){
	float persistance = .5;
	float n = 0.;
	float normK = 0.;
	float f = 4.;
	float amp = 1.;
	int iCount = 0;
	for (int i = 0; i<50; i++){
		n+=amp*noise(p, f);
		f*=2.;
		normK+=amp;
		amp*=persistance;
		if (iCount == res) break;
		iCount++;
	}
	float nf = n/normK;
	return nf*nf*nf*nf;
}

float rand(float n){return fract(sin(n) * 43758.5453123);}

float noise(float p){
	float fl = floor(p);
  float fc = fract(p);
	return mix(rand(fl), rand(fl + 1.0), fc);
}
vec3 getWaveNormal2(vec2 uv2,vec2 worldPosVEC2){
    float G = exp2(-0.5);
    float G2 = 0.2;  // 衰减系数
    float L = 1.5;    // 波峰到波峰之间的距离
    float A = 4.0;    // 波峰的高度
    float S = 0.5;       // 速度,每秒波峰移动的距离
    float w = 2.0*PI/L;     // 角频率常数
    float f = S * 2.0* PI /L; // 相常数
    float dhdx = 0.0;
    float dhdz = 0.0;
    float dhdx_total = 0.0;
    float dhdz_total = 0.0;
    // float n1 = texture2D(noiseTexture, uv2 +time*2e-3).x;
    int N = 3;
    vec2 o[3] = vec2[3](vec2(0.01,0.02),vec2(-0.4,0.8),vec2(0.8,-0.6));
    float n1 = texture2D(noiseTexture, uv2+time*2e-3).x;
    n1 *= 0.5;
    for(int i=0;i<N;i++){
      // vec2 dir = vec2(sin(n1),cos(n1));     // 随机生成波峰移动的方向
      // float angle = (float(i+1) * PI) / float(N);
      // vec2 dir = vec2(cos(angle), sin(angle));  // 不同方向
      vec2 dir = o[i]*n1+vec2(dhdx,dhdz)*5.0*n1; 
      A *= G;
      w *= G2;
      // f *= G;
      float D = dir.x * worldPosVEC2.x + dir.y*worldPosVEC2.y;    // 波峰移动的方向
      float u1 = sin(D*w+time*f);
      float u2 = cos(D*w+time*f);
      dhdx = A * exp(u1-1.0)*w*dir.x*u2; // x偏导
      dhdz = A * exp(u1-1.0)*w*dir.y*u2; // z偏导
      dhdx_total += dhdx;
      dhdz_total += dhdz;
    }
    return normalize(vec3(-dhdx_total,1.0,-dhdz_total));
}
vec3 getWaveNormal(vec2 uv2,vec2 worldPosVEC2){
    float decay_A = 0.77;  // 上升系数
    float decay_w = 1.79;  // 衰减系数
    float L = 20.0;    // 波峰到波峰之间的距离
    float A = 8.0;    // 波峰的高度
    float S = 5.0;       // 速度,每秒波峰移动的距离
    float w = 2.0*PI/L;     // 角频率常数
    float f = S * 2.0* PI /L; // 相常数
    float H = 0.0;
    vec3 dxdydz = vec3(0.0,1.0, 0.0);   // 偏导数
    float dhdx = 0.0;
    float dhdz = 0.0;
    float dhdx_total = 0.0;
    float dhdz_total = 0.0;
    
    int maxTimes = 2;
    // int mystep = int(rd * float(maxTimes)) ;
    vec2 dir = vec2(0.0);     // 随机生成波峰移动的方向
    float n1 = texture2D(noiseTexture, uv2 +time*2e-3).x;
    vec2 dirOrigion = vec2(0.1);     // 随机生成波峰移动的方向
   
    for(int i=0;i<maxTimes;i++){
      // n1 = noise(worldPosVEC2.x / 1280.0 );
      // n2 = noise(worldPosVEC2.y / 4760.0 );
      // n1 = texture2D(noiseTexture, uv2 + float(i)*0.01).x;
      // n2 = texture2D(noiseTexture, uv2 + float(i)*0.03).x;
      // n1 = rand(float(i+1)*decay_A);
      // n2 = rand(float(i+1)*decay_w);
      // float n2 = texture2D(noiseTexture, uv2+float(i)*0.03 +time*7e-3).x;
      dir = vec2(n1*0.01,n1*0.05)*0.7+dirOrigion*0.3 + vec2(dhdx,dhdz)*3e-2;
      A *= decay_A * n1*n1;
      w *= decay_w;
      f *= decay_A;
      float D = dir.x * worldPosVEC2.x + dir.y*worldPosVEC2.y;    // 波峰移动的方向
      float u1 = sin(D*w+time*f);
      float u2 = cos(D*w+time*f);
      dhdx = A * exp(u1-1.0)*w*dir.x*u2; // x偏导
      dhdz = A * exp(u1-1.0)*w*dir.y*u2; // z偏导
      dhdx_total += dhdx;
      dhdz_total += dhdz;
      
    }
    dxdydz = normalize(vec3(-dhdx_total,1.0,-dhdz_total));
    // return vec4(H,dxdydz);
    return dxdydz;
}
void main(void) {
    // vec3 sunPos = vec3(0.0, sin(time*0.1)*1e5, cos(time*0.1)*1e5);
    vec3 sunPos = vec3(0.0,5e4,1e5);
    vec3 shineColor = vec3(0.5);
    vec3 color = vec3(0.0); // 地面颜色
    vec3 cameraPos = (inverse(view)[3]).xyz;
    vec3 worldPos = worldPosition3;
    vec3 viewDir = normalize(cameraPos-worldPosition3);
    vec3 sunDir = normalize(sunPos);
    vec3 halfvec = normalize(viewDir + sunDir); // 计算半程向量
    vec3 worldNormal = getWaveNormal2(vUV,worldPos.xz+1e2);   // 第二种
    // vec3 worldNormal = getWaveNormal(vUV,worldPos.xz+1e2);   // 第一种
    // 水的颜色属性
    vec3 ambientColor  = vec3(0.02, 0.05, 0.1); // 环境光偏深蓝
    vec3 diffuseColor  = vec3(0.0, 0.3, 0.5);   // 漫反射水色
    vec3 specularColor = vec3(0.8, 0.9, 1.0);   // 高光偏白，水面高反射
    
    float I_L = 1.0; // 光源强度
    float k_s = 0.8; // 高光系数
    float k_d = 1.0; // 漫反射系数
    float k_a = 1.0; // 环境光系数
    vec3 Is = k_s * I_L * pow(max(0.0,dot(halfvec, normalize(worldNormal))),50.0) * specularColor;
    vec3 Id = k_d * I_L * max(0.0,dot(sunDir, normalize(worldNormal))) * diffuseColor;
    vec3 Ia = k_a * I_L * ambientColor;
    color = Is+Id+Ia;
    gl_FragColor = vec4(color, 1.0);
}
`;

const waterRenderMaterial = (scene) => {
  // 2. 创建 ShaderMaterial
  const shaderMat = new BABYLON.ShaderMaterial(
    "shaderMat",
    scene,
    {
      vertex: "waterRender", // 对应 waterRenderVertexShader
      fragment: "waterRender", // 对应 waterRenderFragmentShader
    },
    {
      attributes: ["position", "uv"],
      samplers: ["noiseTexture"],
      uniforms: [
        "world",
        "worldView",
        "worldViewProjection",
        "view",
        "projection",
        "time",
        "iResolution",
        "noiseTexture",
      ],
      needAlphaBlending: true,
    }
  );
  return shaderMat;
};

export { waterRenderMaterial };
